package com.cp.weixin.crawler.impl;

import com.cp.weixin.crawler.AbstractCrawler;
import com.cp.weixin.crawler.DownFile;
import com.cp.weixin.crawler.config.Config;
import com.cp.weixin.blog.repository.Record;
import com.cp.weixin.crawler.service.NotPassLinkService;
import com.cp.weixin.blog.service.RecordService;
import com.cp.weixin.util.HtmlUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.safety.Whitelist;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;


import javax.annotation.PostConstruct;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Component
public class WeixinCrawler implements AbstractCrawler {
	public static WeixinCrawler weixinCrawler;
	static Logger log = LogManager.getLogger();
	int totalRecord = 1;
	String query;
	@Autowired
	Config config;

	@Autowired
	RecordService recordService;

	@Autowired
	NotPassLinkService notPassLinkService;

	@PostConstruct
	public void init() {
		weixinCrawler = this;
		weixinCrawler.recordService = this.recordService;
	}

	List<String> list = new ArrayList<String>();
	Document doc = null;


	@Override
	public void getDoc(int pageNum, String query) {
		this.query = query;
		String url = config.getWeixinUrl();
		try {
			log.warn("start page: " + pageNum);
			doc = Jsoup.connect(url+"&page="+pageNum+"&query="+URLEncoder.encode(query, "UTF-8")+"&sst0="+System.currentTimeMillis())
					.header("Cookie", "SUV="+UUID.randomUUID().toString().replace("-", "").toUpperCase()+";" +
							"SNUID="+UUID.randomUUID().toString().replace("-", "").toUpperCase()+"; "+
							config.getWeixinCookie())
					.userAgent(HtmlUtil.randomUA())
					.ignoreContentType(true)
					.followRedirects(true)
					.ignoreHttpErrors(true)
					.get();
		} catch(Exception ex) {
			ex.printStackTrace();
			log.error("get document exceptin： "+ex.getMessage());
		}
	}

	@Override
	public void getLink(){
		list = new ArrayList<String>();
		if(doc!=null){
			if(totalRecord == 1){
				try {
					totalRecord = Integer.parseInt(doc.select("#pagebar_container > div").text().replaceAll("[\u4E00-\u9FA5,，\\s]", ""));
					log.warn("总记录："+totalRecord);
				} catch (Exception ex) {
					log.error("获取页码异常：" + ex.getMessage());
				}
			}

			Elements eles = doc.select("li > div.txt-box > h3 > a");
			if(eles.isEmpty()) {
				log.error("doc："+doc.text());
			} else {
				// md5（url） 去重，但是url会变，放弃
				String dataLink = "";
//				for (Element ele : eles) {
//					if (ele.attr("data-share").startsWith("http")) {
//						dataLink = ele.attr("data-share");
//					} else {
//						dataLink = "http://weixin.sogou.com/api/share/" + ele.attr("data-share");
//					}
//					Record record = recordService.getRecordByUrlMd5(DigestUtils.md5DigestAsHex(dataLink.getBytes()));
//					if(record==null){
//						list.add(dataLink);
//					} else {
//						log.warn("重复url，不加入爬虫队列:"+dataLink);
//					}
//				}

				//改用标题去重
				String title = "";
				for(Element ele : eles) {
					title = ele.text();
					Record record = recordService.getRecordByTitle(title);
					if(record==null){
						if (ele.attr("data-share").startsWith("http")) {
							dataLink = ele.attr("data-share");
						} else {
							dataLink = "http://weixin.sogou.com/api/share/" + ele.attr("data-share");
						}
						list.add(dataLink);
					} else {
						log.warn("重复内容，不加入爬虫队列:"+title);
					}
				}
			}
		} else {
			log.error("doc is null");
		}
		//休眠
		sleep();
	}

	@Override
	public void getDetail() {
	    Document doc = null;
        Whitelist whitelist = Whitelist.relaxed();
//        Cleaner cleaner = new Cleaner(whitelist);
        String title = "";
        String content = "";
        String source = "";
        String pubtime = "";
        String uid = "";
        for(String link : list) {
            try{
                doc = Jsoup.connect(link).header("Cookie", "SUV="+UUID.randomUUID().toString().replace("-", "").toUpperCase()+";"+config.getWeixinCookie())
		                .userAgent(HtmlUtil.randomUA())
			            .ignoreContentType(true)
			            .followRedirects(true)
			            .ignoreHttpErrors(true).get();
	            uid = UUID.randomUUID().toString();
                //删除link节点
                doc.select("link, script");
//               doc = cleaner.clean(doc);
	            parserImg(doc, uid);
	            title = doc.select("#activity-name").text();
	            source = doc.select("#js_name").text();
	            content = doc.select("#js_content").html().replaceAll("<\\s*?script[^>]*?>[\\s\\S]*?<\\s*?/\\s*?script\\s*?>", "").replaceAll("[\r\n]", "");
	            pubtime = "";
				try {
					int isAdd = recordService.addRecord(uid, title, content, source, new Date(), new Date(), DigestUtils.md5DigestAsHex(link.getBytes()), query, 0, 0, 999, "");
					if (isAdd == 1) {
						log.warn("success : " + link);
					} else {
						log.error("fail : " + link);
					}
				}catch (DuplicateKeyException e){
					log.warn("重复链接："+link);
				} catch(Exception ex) {
					ex.printStackTrace();
					log.error("插入数据库异常："+ex.getMessage());
				}
            }catch (Exception ex){
				try {
					int notPass = notPassLinkService.addLink(link);
					if(notPass == 1) {
						log.warn("success add link to not pass: "+link);
					} else {
						log.error("fail add link to not pass: "+link);
					}
				}catch (DuplicateKeyException e){
					log.warn("not pass重复链接："+link);
				} catch(Exception exx) {
					exx.printStackTrace();
					log.error("add not pass error : "+ex.getMessage());
				}
            }
            //休眠
	        sleep();
        }
	}

	@Override
	public int getTotalRecord() {
		return totalRecord;
	}

	/**
	 * 下载图片文件，且把图片引用目录改为本地目录
	 * @param doc
	 * @param folder
	 */
	@Override
	public void parserImg(Document doc, String folder){
		Elements imgEles = doc.select("img");
		String fileName = "";
		for(Element imgEle : imgEles){
			if(imgEle.hasAttr("data-src")){
				fileName = UUID.randomUUID().toString()+"."+(imgEle.attr("data-type")==null?"png ":imgEle.attr("data-type"));
//				imgEle.attr("src", "images/"+fileName);
				imgEle.attr("src", "/images/weixin/"+folder+"/"+fileName);
				new Thread(new DownFile(imgEle.absUrl("data-src"), config.getWeixinImagePath()+folder+File.separator, fileName)).start();
				//删除原始链接
				imgEle.removeAttr("data-src");
				imgEle.removeAttr("data-before-oversubscription-url");
			}
		}
	}

	/**
	 * 下载视频文件，且更改视频目录为本地视频（还需下载视频封面）
	 * @param doc
	 * @param folder
	 */
	@Override
	public void parserVideo(Document doc, String folder){
		//todo

	}

	/**
	 * 下载音频文件，且更改音频文件为本地音频
	 * @param doc
	 * @param savePath
	 */
	@Override
	public void psrserAudio(Document doc, String savePath) {
		//todo

	}

	public void sleep() {
		//5-15随机数
		int randomNum = ((int)(1 + Math.random()*10) + 6)*1000;
		log.warn("随机休眠："+randomNum + "ms");
		try {
			Thread.sleep(randomNum);
		} catch(Exception ex) {
			log.error("随机休眠被打断："+ex.getMessage());
		}

	}

	public String getQuery() {
		return query;
	}

	public void setQuery(String query) {
		this.query = query;
	}
}
